<script lang="ts">
    import {
        type ColumnDef,
        type ColumnFiltersState,
        getCoreRowModel,
        getPaginationRowModel,
        type PaginationState,
    } from "@tanstack/table-core";
    import {
        createSvelteTable,
        FlexRender,
    } from "$lib/components/ui/data-table/index.js";
    import * as Table from "$lib/components/ui/table/index.js";
    import * as Pagination from "$lib/components/ui/pagination";
    import * as Lucid from "@lucide/svelte";
    import { Input } from "$lib/components/ui/input";
    import { Button } from "$lib/components/ui/button";
    import * as Popover from "$lib/components/ui/popover";
    import * as Command from "$lib/components/ui/command";
    import { getShape, type FilterTyp, filterTyps } from "./columns";
    import { cn } from "$lib/utils";
    import * as Drawer from "$lib/components/ui/drawer";
    import AddSpaceForm from "./add-space-form.svelte";
    import type { AddSpace } from "./schema";
    import { axiosIns, toastErr, type Space, type SpaceUser } from "../index";
    import { toast } from "svelte-sonner";
    import { onMount } from "svelte";

    let {
        userId,
        enterSpace,
    }: { userId: number; enterSpace: (space: Space) => void } = $props();
    let pagination = $state<PaginationState>({
        pageIndex: 1,
        pageSize: 5,
    });
    let spaces = $state<Space[]>([]);
    let count = $state(0);
    let spaceLis = async () => {
        await axiosIns
            .post(
                `/spaces/lis?cur=${pagination.pageIndex - 1}&num=${pagination.pageSize}`,
                {},
            )
            .then((res) => {
                const { total, data } = res.data;
                count = total;
                spaces = data;
            })
            .catch(toastErr);
    };
    let spaceAdd = (data: AddSpace) => {
        axiosIns
            .post("/spaces/add", data)
            .then(async () => {
                toast.success("Success.");
                addSpaceDrawerOpen = false;
                await spaceLis();
            })
            .catch(toastErr);
    };
    let spaceDel = (spaceId: number) => {
        axiosIns
            .delete(`/spaces/${spaceId}`)
            .then(async () => {
                toast.success("Success.");
                addSpaceDrawerOpen = false;
                await spaceLis();
            })
            .catch(toastErr);
    };
    let filterComboboxOpen = $state(false);
    let columnFilterTyp = $state<FilterTyp>(filterTyps[0]);
    let columnFilters = $state<ColumnFiltersState>([]);
    let shape = getShape(userId, spaceDel, enterSpace);
    let table = createSvelteTable({
        get data() {
            return spaces;
        },
        columns: shape.columns,
        state: {
            get pagination() {
                return pagination;
            },
            get columnFilters() {
                return columnFilters;
            },
        },
        onPaginationChange: (updater) => {
            if (typeof updater === "function") {
                pagination = updater(pagination);
            } else {
                pagination = updater;
            }
        },
        onColumnFiltersChange: (updater) => {
            if (typeof updater === "function") {
                columnFilters = updater(columnFilters);
            } else {
                columnFilters = updater;
            }
        },
        getCoreRowModel: getCoreRowModel(),
        manualPagination: true,
        get rowCount() {
            return count;
        },
    });
    let addSpaceDrawerOpen = $state(false);
    let onPageChange = (page: number) => {
        pagination.pageIndex = page;
        spaceLis();
    };

    onMount(() => {
        spaceLis();
    });
</script>

<div class="w-full h-full flex flex-col">
    <div class="flex items-center py-2">
        <Input
            placeholder={`根据${columnFilterTyp.label}检索...`}
            value={(table
                .getColumn(columnFilterTyp.value)
                ?.getFilterValue() as string) ?? ""}
            onchange={(e) => {
                table
                    .getColumn(columnFilterTyp.value)
                    ?.setFilterValue(e.currentTarget.value);
            }}
            oninput={(e) => {
                table
                    .getColumn(columnFilterTyp.value)
                    ?.setFilterValue(e.currentTarget.value);
            }}
            class="max-w-sm"
        />
        <Popover.Root bind:open={filterComboboxOpen}>
            <Popover.Trigger>
                {#snippet child({ props })}
                    <Button
                        {...props}
                        variant="outline"
                        class="w-[200px] justify-between ml-2"
                        role="combobox"
                    >
                        {columnFilterTyp.label}
                        <Lucid.ChevronsUpDownIcon class="opacity-50" />
                    </Button>
                {/snippet}
            </Popover.Trigger>
            <Popover.Content class="w-[200px] p-0">
                <Command.Root>
                    <Command.List>
                        {#each filterTyps as filterTyp (filterTyp.value)}
                            <Command.Item
                                value={filterTyp.value}
                                onSelect={() => {
                                    columnFilterTyp = filterTyp;
                                    filterComboboxOpen = false;
                                }}
                            >
                                <Lucid.CheckIcon
                                    class={cn(
                                        columnFilterTyp.value !==
                                            filterTyp.value &&
                                            "text-transparent",
                                    )}
                                />
                                {filterTyp.label}
                            </Command.Item>
                        {/each}
                    </Command.List>
                </Command.Root>
            </Popover.Content>
        </Popover.Root>
        <div class="flex-1"></div>
        <Drawer.Root bind:open={addSpaceDrawerOpen}>
            <Drawer.Trigger>
                <Button class="ml-2" onclick={() => (addSpaceDrawerOpen = true)}
                    ><Lucid.CalendarPlus />新建课程</Button
                >
            </Drawer.Trigger>
            <Drawer.Content>
                <div class="flex justify-center">
                    <div class="w-1/2 min-w-[800px] my-8">
                        <AddSpaceForm onSummit={spaceAdd} />
                    </div>
                </div>
            </Drawer.Content>
        </Drawer.Root>
    </div>
    <div class="rounded-md border flex-1 overflow-y-auto">
        <Table.Root>
            <Table.Header>
                {#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
                    <Table.Row>
                        {#each headerGroup.headers as header (header.id)}
                            <Table.Head
                                colspan={header.colSpan}
                                style="width: {header.getSize()}px;"
                            >
                                {#if !header.isPlaceholder}
                                    <FlexRender
                                        content={header.column.columnDef.header}
                                        context={header.getContext()}
                                    />
                                {/if}
                            </Table.Head>
                        {/each}
                    </Table.Row>
                {/each}
            </Table.Header>
            <Table.Body>
                {#each table.getRowModel().rows as row (row.id)}
                    <Table.Row data-state={row.getIsSelected() && "selected"}>
                        {#each row.getVisibleCells() as cell (cell.id)}
                            <Table.Cell>
                                <FlexRender
                                    content={cell.column.columnDef.cell}
                                    context={cell.getContext()}
                                />
                            </Table.Cell>
                        {/each}
                    </Table.Row>
                {:else}
                    <Table.Row>
                        <Table.Cell colspan={shape.count} align="center">
                            Nothing found.
                        </Table.Cell>
                    </Table.Row>
                {/each}
            </Table.Body>
        </Table.Root>
    </div>
    <Pagination.Root
        class="mt-2"
        {count}
        perPage={pagination.pageSize}
        {onPageChange}
    >
        {#snippet children({ pages, currentPage })}
            <Pagination.Content>
                <Pagination.Item>
                    <Pagination.PrevButton>
                        <Lucid.ChevronLeftIcon class="size-4" />
                        <span class="hidden sm:block">上一页</span>
                    </Pagination.PrevButton>
                </Pagination.Item>
                {#each pages as page (page.key)}
                    {#if page.type === "ellipsis"}
                        <Pagination.Item>
                            <Pagination.Ellipsis />
                        </Pagination.Item>
                    {:else}
                        <Pagination.Item>
                            <Pagination.Link
                                {page}
                                isActive={currentPage === page.value}
                            >
                                {page.value}
                            </Pagination.Link>
                        </Pagination.Item>
                    {/if}
                {/each}
                <Pagination.Item>
                    <Pagination.NextButton>
                        <span class="hidden sm:block">下一页</span>
                        <Lucid.ChevronRightIcon class="size-4" />
                    </Pagination.NextButton>
                </Pagination.Item>
            </Pagination.Content>
        {/snippet}
    </Pagination.Root>
</div>
